package hos.load

import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.LifecycleOwner

/**
 * <p>Title: LoadableImpl </p>
 * <p>Description:  </p>
 * <p>Company: www.mapuni.com </p>
 *
 * @author : 蔡俊峰
 * @date : 2024-08-15 9:14
 * @version : 1.0
 */
abstract class LoadableImpl(lifecycleOwner: LifecycleOwner) : Loadable {

    protected open var loadStatus: LoadStatus = LoadStatus.NOT_LOADED

    protected open var throwable: Throwable? = null

    private val mLoadReadableList by lazy { mutableListOf<Runnable>() }

    private val mLoadStatusChangedList by lazy { mutableListOf<LoadStatusChangedListener>() }

    init {
        lifecycleOwner.lifecycle.addObserver(object : DefaultLifecycleObserver {
            override fun onCreate(owner: LifecycleOwner) {
                this@LoadableImpl.onCreate()
            }

            override fun onDestroy(owner: LifecycleOwner) {
                this@LoadableImpl.onDestroy()
                owner.lifecycle.removeObserver(this)
            }
        })
    }

    open fun onCreate() {

    }

    open fun onDestroy() {
        throwable = null
        loadStatus = LoadStatus.NOT_LOADED
        mLoadReadableList.clear()
        mLoadStatusChangedList.clear()
    }

    override fun getStatus(): LoadStatus {
        return loadStatus
    }

    override fun getLoadError(): Throwable? {
        return throwable
    }

    override fun cancelLoad() {
        loadStatus = LoadStatus.NOT_LOADED
    }

    override fun loadAsync() {
        try {
            // 正在加载中
            if (loadStatus == LoadStatus.LOADING) {
                return
            }
            loadStatus = LoadStatus.LOADING
            loading()
            if (loadStatus == LoadStatus.LOADING) {
                loadStatus = LoadStatus.LOADED
            }
        } catch (e: Throwable) {
            throwable = e
            loadStatus = LoadStatus.FAILED_TO_LOAD
        } finally {
            if (loadStatus != LoadStatus.NOT_LOADED) {
                mLoadReadableList.forEach {
                    it.run()
                }
            }
        }
    }

    @Throws(Throwable::class)
    abstract fun loading()

    override fun retryLoadAsync() {
        // 正在加载中
        if (loadStatus == LoadStatus.LOADING) {
            return
        }
        loadAsync()
    }

    override fun addDoneLoadingListener(runnable: Runnable) {
        if (!mLoadReadableList.contains(runnable)) {
            mLoadReadableList.add(runnable)
        }
    }

    override fun removeDoneLoadingListener(runnable: Runnable): Boolean {
        if (mLoadReadableList.contains(runnable)) {
            return mLoadReadableList.remove(runnable)
        }
        return true
    }

    override fun addLoadStatusChangedListener(listener: LoadStatusChangedListener) {
        if (!mLoadStatusChangedList.contains(listener)) {
            mLoadStatusChangedList.add(listener)
        }
    }

    override fun removeLoadStatusChangedListener(listener: LoadStatusChangedListener): Boolean {
        if (mLoadStatusChangedList.contains(listener)) {
            return mLoadStatusChangedList.remove(listener)
        }
        return true
    }
}